package com.zkjl.protect_business.service.impl;

import cn.afterturn.easypoi.entity.ImageEntity;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.crypto.digest.DigestAlgorithm;
import cn.hutool.crypto.digest.Digester;
import cn.hutool.extra.pinyin.PinyinUtil;
import cn.hutool.json.JSONUtil;
import com.zkjl.protect_business.common.BaseException;
import com.zkjl.protect_business.common.Status;
import com.zkjl.protect_business.common.UserThreadLocal;
import com.zkjl.protect_business.dto.document.UploadDocumentDTO;
import com.zkjl.protect_business.entity.*;
import com.zkjl.protect_business.repository.BusinessRepository;
import com.zkjl.protect_business.repository.OrganizationRepository;
import com.zkjl.protect_business.repository.PBFileRepository;
import com.zkjl.protect_business.repository.TemplateRepository;
import com.zkjl.protect_business.service.*;
import com.zkjl.protect_business.utils.*;
import com.zkjl.protect_business.vo.ParamVO;
import com.zkjl.protect_business.vo.UploadAttachmentDetaileVO;
import com.zkjl.protect_business.vo.statistic.GroupVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.*;
import org.elasticsearch.index.reindex.BulkByScrollResponse;
import org.elasticsearch.index.reindex.BulkByScrollTask;
import org.elasticsearch.index.reindex.ReindexRequest;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramInterval;
import org.elasticsearch.search.aggregations.bucket.histogram.ParsedDateHistogram;
import org.joda.time.DateTimeZone;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.*;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.*;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.zip.ZipOutputStream;

import static com.zkjl.protect_business.common.Consts.*;
import static com.zkjl.protect_business.common.Status.*;

@Service
@Slf4j
public class DocumentServiceImpl implements DocumentService {

    @Autowired
    ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Autowired
    TemplateRepository templateRepository;
    @Autowired
    BusinessRepository businessRepository;
    @Autowired
    TemplateService templateService;
    @Autowired
    FileService fileService;
    @Autowired
    BusinessService businessService;
    @Autowired
    OrganizationService organizationService;
    @Autowired
    OrganizationRepository organizationRepository;
    @Autowired
    ArchiveService archiveService;
    @Autowired
    PBFileRepository pbFileRepository;

    @Value(value = "${file.export.url}")
    String exportUrl;

    @Value(value = "${upload.path}")
    private String uploadPath;
    @Autowired
    RestHighLevelClient client;



    @Autowired
    LogService logService;
    @Autowired
    WordUtil wordUtil;


    public Object saveDocument(MultipartFile file, String templateId, UploadDocumentDTO uploadDocumentDTO) throws IOException {

        Optional<Template> repository = templateRepository.findById(templateId);
        if (!repository.isPresent()) {
            throw new BaseException(BAD_REQUEST.getCode(), "未找到对应模板信息！");
        }

        Template template = repository.get();
        //所属业务分类
        String businessId = template.getBusinessId();
        Business business = businessService.get(businessId);
        String name = business.getName();
        String pname = business.getPname();
        String orgFieldName = business.getOrgFieldName();
        if (StringUtils.isBlank(orgFieldName)) {
            throw new BaseException(DATA_NOT_EXIST.getCode(), "请先指定当前业务中的单位信息字段！");
        }

        //指定数据字段
        uploadDocumentDTO.setOrgFieldName(orgFieldName);
        uploadDocumentDTO.setIdCardFieldName(business.getIdCardFieldName());
        uploadDocumentDTO.setOccurredTime(business.getOccurredTime());
        uploadDocumentDTO.setUniqueFieldName(business.getUniqueFieldName());

        IndexCoordinates indexCoordinates = QueryUtil.createIndex(name, pname);
        List<DocField> docFields = template.getFields();

        //保存文件文件上传失败！
        String fileId = fileService.uploadFile(file);
        if (StringUtils.isBlank(fileId)) {
            throw new BaseException(ERROR.getCode(), "文件上传失败！");
        }

        String originalFilename = file.getOriginalFilename();
        String suffix = FileUtil.getSuffix(originalFilename).toLowerCase();
        Object result = null;
        PBFile pbFile = fileService.get(fileId);
        String path = pbFile.getPath();
        File file1 = FileUtil.file(path);

        if ("doc,docx".contains(suffix)) {
            result = parsingWord(docFields, file1, indexCoordinates, fileId, uploadDocumentDTO);

        } else if ("xls,xlsx".contains(suffix)) {
            result = parsingExcel(docFields, file1, indexCoordinates, fileId, uploadDocumentDTO);
        }

        logService.save("业务文档", file.getOriginalFilename(), OPERATION_UPLOAD);


        return result;

    }

    @Override
    public Object get(String id, String businessId) {

        IndexCoordinates index = businessService.getIndex(businessId);

        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
        BoolQueryBuilder qb = QueryBuilders.boolQuery();

        qb.filter(QueryBuilders.termQuery("id.keyword", id));
        queryBuilder.withQuery(qb);
        NativeSearchQuery build = queryBuilder.build();

        SearchHit<Object> objectSearchHit = elasticsearchRestTemplate.searchOne(build, Object.class, index);
        Object content = objectSearchHit.getContent();
        return content;
    }

    @Override
    public Boolean recovery(String indexName) {


        String oldIndexName = indexName.replace(INDEX_PREFIX, DEL_INDEX_PREFIX);

        //删除索引的逻辑是直接把原来的索引名字改掉
        ReindexRequest reindexRequest = new ReindexRequest();
        reindexRequest.setSourceIndices(oldIndexName);
        reindexRequest.setDestIndex(indexName);
        reindexRequest.setRefresh(true);

        try {
            BulkByScrollResponse reindex = client.reindex(reindexRequest, RequestOptions.DEFAULT);

            BulkByScrollTask.Status status = reindex.getStatus();

        } catch (IOException e) {
            e.printStackTrace();
            log.error("恢复索引失败");
        }

        return true;
    }

    @Override
    public void updateHistoricalData(String businessId) {

        Business business = businessService.get(businessId);

        IndexCoordinates index = businessService.getIndex(businessId);

        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
        SearchHits<Object> search = elasticsearchRestTemplate.search(queryBuilder.build(), Object.class, index);
        search.stream().forEach(searchHit -> {
            Map<String, Object> content = (Map<String, Object>) searchHit.getContent();
            processData(content, business, index);
        });

    }

    /**
     * 处理单条数据
     * @param content
     * @param business
     * @param index
     */
    @Async
    @Override
    public void processData(Map<String, Object> content, Business business, IndexCoordinates index) {

        String orgFieldName = business.getOrgFieldName();
        String idCardFieldName = business.getIdCardFieldName();
        String occurredTime = business.getOccurredTime();

        Map<String, Object> newMap = new HashMap<>();
        content.forEach((key, value) -> {
            //把历史数据处理更新一下，找不到的就不更新
            if (key.equals(orgFieldName)) {

                List<String> allPame = organizationService.findAllPame(value + "");
                newMap.put(ATTRIBUTION_ORG_NAMES, allPame);

                Organization organization = organizationService.find(value + "");
                if (organization != null) {
                    String organizationId = organization.getId();
                    String orgName = organization.getOrgName();
                    newMap.put(ATTRIBUTION_ORG_NAME, orgName);
                    newMap.put(ATTRIBUTION_ORG_ID, organizationId);
                }
            } else if (key.equals(occurredTime)) {
                newMap.put(OCCURRED_TIME, value);
            } else if (key.equals(idCardFieldName)) {
                newMap.put(ID_CARD, value);
            }
        });

        content.putAll(newMap);

        //更新数据
        String id = MapUtil.getStr(content, "id");
        IndexQueryBuilder builder = new IndexQueryBuilder() //
                .withId(id) //
                .withObject(content);
        elasticsearchRestTemplate.index(builder.build(), index);
    }


    /**
     * 根据单个条件获取文档
     *
     * @param key
     * @param value
     * @return
     */
    @Override
    public Object get(IndexCoordinates indexCoordinates, String key, Object value) {


        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
        BoolQueryBuilder qb = QueryBuilders.boolQuery();

        qb.filter(QueryBuilders.termQuery(key + ".keyword", value));
        queryBuilder.withQuery(qb);
        NativeSearchQuery build = queryBuilder.build();
        SearchHits<Object> search1 = elasticsearchRestTemplate.search(build, Object.class, indexCoordinates);
        List<Object> collect = search1.stream().map(SearchHit::getContent).collect(Collectors.toList());

        if (CollUtil.isEmpty(collect)) {
            return null;
        }
        if (collect.size() > 1) {
            throw new BaseException(DATA_EXIST, key + value + "数据存在多条！");
        }
        return collect.get(0);
    }

    @Override
    public Object saveOrupdate(String businessId, Map<String, Object> param) {

        Business business = businessService.get(businessId);

        IndexCoordinates index = businessService.getIndex(businessId);

        //所有字段
        List<BusinessField> fields = business.getFields();
        if (CollUtil.isEmpty(fields)) {
            throw new BaseException(DATA_NOT_EXIST.getCode(), "该业务未找到字段，请先配置字段！");
        }
        //处理字段类型
        HashMap<String, String> map = new HashMap<>();
        fields.stream().forEach(field1->{
            String key = field1.getKey();
            String type = field1.getType();
            map.put(key, type);
        });

        //如果指定了唯一字段，上传的数据必须要有这个字段
        String uniqueFieldName = business.getUniqueFieldName();
        //必须要有单位
        String orgFieldName = business.getOrgFieldName();

        UploadDocumentDTO uploadDocumentDTO = new UploadDocumentDTO();
        //指定数据字段
        uploadDocumentDTO.setOrgFieldName(orgFieldName);
        uploadDocumentDTO.setIdCardFieldName(business.getIdCardFieldName());
        uploadDocumentDTO.setOccurredTime(business.getOccurredTime());
        uploadDocumentDTO.setUniqueFieldName(business.getUniqueFieldName());

        //是否存在唯一值
        Boolean haveUnique = false;
        //没有设置字段就不需要
        if(StringUtils.isEmpty(uniqueFieldName)){
            haveUnique = true;
        }

        //是否有单位
        Boolean haveOrg = false;


        Map<String, Object> result = new HashMap<>();

        Set<Map.Entry<String, Object>> entries = param.entrySet();
        for (Map.Entry<String, Object> entry : entries) {

            String key = entry.getKey();
            //修改的时候数据归属字段不处理，解决单位不变更的问题
            if (key.equals(ATTRIBUTION_ORG_NAMES) || key.equals(ATTRIBUTION_ORG_NAME)) {
                continue;
            }

            Object value = entry.getValue();
            String type = map.get(key);

            if (StringUtils.isNotBlank(uniqueFieldName) && key.equals(uniqueFieldName)) {
                haveUnique = true;
            }
            if (key.equals(orgFieldName)) {
                haveOrg = true;
            }
            if (StringUtils.isNotBlank(type) &&"date,time,month".contains(type) ) {
                if (StringUtils.isNotBlank(value + "")) {
                    Long date = formatDate(key, value + "");
                    result.put(key, date);
                }else {
                    result.put(key, 0);
                }

            } else {
                result.put(key, value);
            }

            specifiedField(key, value,uploadDocumentDTO,result,index);

        }

        if (!haveUnique) {
            throw new BaseException(DATA_NOT_EXIST.getCode(), "未找到唯一字段 " + uniqueFieldName + "的值");
        }

        if (!haveOrg) {
            throw new BaseException(DATA_NOT_EXIST.getCode(), "未找到单位字段 " + orgFieldName + "的值");
        }

        String file_id = MapUtil.getStr(result, "file_id");
        IndexQueryBuilder indexQueryBuilder = indexDoc(result, file_id, index);
        String index1 = elasticsearchRestTemplate.index(indexQueryBuilder.build(), index);


        return index1;
    }

    @Override
    public PageImpl<Object> page(String businessId,Map<String, Object> param) {

        Business business = businessService.get(businessId);
        String orgFieldName = business.getOrgFieldName();
        String name = business.getName();
        //处理字段类型
        List<BusinessField> fields = business.getFields();
        HashMap<String, Object> map = new HashMap<>();
        fields.stream().forEach(field1->{
            String key = field1.getKey();
            String type = field1.getType();
            map.put(key, type);
        });

        String pname = business.getPname();
        IndexCoordinates indexCoordinates = QueryUtil.createIndex(name, pname);

        //存档id 如果选择了存档就直接查询存档里面的数据
        String archiveId = MapUtil.getStr(param, "archiveId");
        if (StringUtils.isNotBlank(archiveId)) {
            Archive archive = archiveService.get(archiveId);
            String indexName = archive.getIndexName();
            indexCoordinates = IndexCoordinates.of(indexName);
        }

        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
        BoolQueryBuilder qb = QueryBuilders.boolQuery();

        //全局关键词
        String search = MapUtil.getStr(param, "search");
        if (StringUtils.isNotEmpty(search)) {
            //精确匹配  https://blog.csdn.net/hereiskxm/article/details/47979013
            MultiMatchQueryBuilder type = new MultiMatchQueryBuilder(search).type(MultiMatchQueryBuilder.Type.PHRASE).slop(0);
            qb.filter(type);
        }

        if (param != null) {
            Set<Map.Entry<String, Object>> entries = param.entrySet();
            for (Map.Entry<String, Object> entry : entries) {
                String key = entry.getKey();
                //排除这几个自定义的字段
                if ("search,sort,order,pageSize,pageNum,archiveId".contains(key)) {
                    continue;
                }
                Object value = entry.getValue();
                //时间格式 中间用~分隔
                if ((value + "").contains("~")) {
                    String string = value.toString();
                    String[] split = string.split("~");
                    qb.filter(QueryBuilders.rangeQuery(key).gte(split[0]));
                    qb.filter(QueryBuilders.rangeQuery(key).lte(split[1]));
                }else {

                    //如果用指定单位字段查询就在特定字段里面取查
                    if (key.equals(orgFieldName)) {

                        BoolQueryBuilder qb2 = QueryBuilders.boolQuery();
                        qb2.should(new TermsQueryBuilder(ATTRIBUTION_ORG_NAMES + ".keyword", value));
                        qb2.should(QueryBuilders.termQuery(key + ".keyword", value));
                        qb.filter(qb2);
//                        qb.filter(QueryBuilders.termQuery(key + ".keyword", value));
                    }else {
                        if ("list".equals(map.get(key))) {
                            qb.filter(QueryBuilders.termQuery(key + ".keyword", value));
                        }else {
                            qb.filter(new QueryStringQueryBuilder("\"" + value + "\"").field(key).defaultOperator(Operator.AND));
                        }
                    }

                }

            }
        }



        Sort.Direction directionSort = Sort.Direction.DESC;
        String direction = MapUtil.getStr(param, "sort");
        if (StringUtils.isNotEmpty(direction)) {
            String lowerCase = direction.toLowerCase();
            if ("desc".equals(lowerCase)) {
                directionSort = Sort.Direction.DESC;
            } else if ("asc".equals(lowerCase)) {
                directionSort = Sort.Direction.ASC;
            }
        }

        String field = MapUtil.getStr(param, "order");
        if (StringUtils.isEmpty(field)) {
            field = "create_time";
        }else {
            //判定类型
            if (CollUtil.isEmpty(fields)) {     //没有字段的话就默认是字符串查询，可能会报错后期看怎么处理
                field += ".keyword";
            }else {
                if ("text,string,list".contains(map.get(field) + "")) {
                    field += ".keyword";
                }
            }

        }

        Integer pageNum = MapUtil.getInt(param, "pageNum") != null ? MapUtil.getInt(param, "pageNum") : 1;
        Integer pageSize = MapUtil.getInt(param, "pageSize") != null ? MapUtil.getInt(param, "pageSize") : 10;
        //分页

        Pageable pageable = PageRequest.of( pageNum - 1,pageSize ,directionSort, field);
        queryBuilder.withPageable(pageable);

        //只能获取当前机构下的文档
        qb.filter(new TermsQueryBuilder(ATTRIBUTION_ORG_NAMES +".keyword", UserThreadLocal.getOrg()));
        queryBuilder.withQuery(qb);
        NativeSearchQuery build = queryBuilder.build();
        build.setTrackTotalHits(true);  //显示所有数量 https://elasticsearch.cn/question/7655

        SearchHits<Object> search1 = elasticsearchRestTemplate.search(build, Object.class, indexCoordinates);
        List<Object> collect = search1.stream().map(SearchHit::getContent).collect(Collectors.toList());
        long total = search1.getTotalHits();

        PageImpl page = new PageImpl(collect, pageable, total);

        return page;
    }

    @Override
    public List<Map<String, Object> > list(Map<String, Object> param, String indexName) {

        String pinyin = PinyinUtil.getPinyin(indexName, "");
        IndexCoordinates indexCoordinates = IndexCoordinates.of(INDEX_PREFIX + pinyin);

        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
        BoolQueryBuilder qb = QueryBuilders.boolQuery();

        //id
        List<String> docIds = (List<String>) param.get("docIds");
        if (CollUtil.isNotEmpty(docIds)) {
            qb.filter(new TermsQueryBuilder("id",docIds));
        }
        //模糊搜索
        String search = MapUtil.getStr(param, "search");
        if (StringUtils.isNotEmpty(search)) {
            //精确匹配  https://blog.csdn.net/hereiskxm/article/details/47979013
            MultiMatchQueryBuilder type = new MultiMatchQueryBuilder(search).type(MultiMatchQueryBuilder.Type.PHRASE).slop(0);
            qb.filter(type);
        }

        Set<Map.Entry<String, Object>> entries = param.entrySet();
        for (Map.Entry<String, Object> entry : entries) {
            String key = entry.getKey();
            //排除这几个自定义的字段
            if ("search,docIds,sort,order,pageSize,pageNum".contains(key)) {
                continue;
            }
            Object value = entry.getValue();
            //时间格式 中间用~分隔
            if ((value + "").contains("~")) {
                String string = value.toString();
                String[] split = string.split("~");
                qb.filter(QueryBuilders.rangeQuery(key).gte(split[0]));
                qb.filter(QueryBuilders.rangeQuery(key).lt(split[1]));
            }else {
                qb.filter(new QueryStringQueryBuilder(value + "").field(key).defaultOperator(Operator.AND));
            }

        }

        queryBuilder.withQuery(qb);
        SearchHits<Object> search1 = elasticsearchRestTemplate.search(queryBuilder.build(), Object.class, indexCoordinates);
        List<Map<String, Object> > collect = search1.stream().map(searchHit ->{
            Map<String, Object> content = (Map<String, Object>) searchHit.getContent();
            return content;
        }).collect(Collectors.toList());

        return collect;
    }


    /**
     * 处理字段格式
     * @param fields
     * @param list
     * @return
     */
    public List<Map<String, Object>> processingTimeFormat(List<DocField> fields, List<Map<String, Object>> list) {

        //判定类型
        HashMap<String, Object> map = new HashMap<>();
        fields.stream().forEach(field1 -> {
            String key = field1.getKey();
            String type1 = field1.getType();
            map.put(key, field1);
        });

        list.stream().forEach(map2 ->{
            //处理类型
            Set<Map.Entry<String, Object>> entries = map2.entrySet();
            for (Map.Entry<String, Object> entry : entries) {
                String key = entry.getKey();
                DocField docField = (DocField) map.get(key);
                String type = "";
                if (docField != null) {
                    type = docField.getType();
                }
                //没有的设置一个空值
                if (StringUtils.isBlank(entry.getValue() + "")) {
                    entry.setValue(" ");
                    continue;
                }

                if ("date".equals(type)) {
                    if ( entry.getValue() instanceof Long) {

                        Long value = (Long) entry.getValue();
                        DateTime date = DateUtil.date(value);
                        String str = date.toDateStr();
                        entry.setValue(str);
                    }

                } else if("month".equals(type)){
                    if ( entry.getValue() instanceof Long) {

                        Long value = (Long) entry.getValue();
                        DateTime date = DateUtil.date(value);
                        int month = date.month();
                        int year = date.year();
                        entry.setValue(year + "年" + month + "月");
                    }


                }else if ("image".equals(type)) {  //处理写入图片
                    Object value = entry.getValue();
                    String path = value + "";
                    String replace = path.replace("/files/", "");
                    String newPath = uploadPath+ "/" + replace;

                    Integer cellWidth = docField.getCellWidth();
                    Integer cellHeight = docField.getCellHeight();
                    ImageEntity image = WordUtil.createImage(newPath, cellWidth, cellHeight);
                    entry.setValue(image);

                }
            }

        });

        //处理没有的key
        List<Map<String, Object>> maps = ExportUtil.toDealWithMap(list, fields);
        return maps;

    }


    @Override
    public String export(String templateId, Map<String, Object> param) throws IOException {

        Template template = templateService.get(templateId);
        String type = template.getType();
        String fileId = template.getFileId();
        List<DocField> fields = template.getFields();


        //获取文件存放路径
        PBFile pbFile = fileService.get(fileId);
        String path = pbFile.getPath();
        String fileName = pbFile.getName();

        String businessId = template.getBusinessId();
        Business business = businessService.get(businessId);
        String name = business.getName();
        String pname = business.getPname();
        List<Map<String, Object>> list = list(param, pname + "_" + name);


        if (CollUtil.isEmpty(list)) {
            return "";
        }

        List<Map<String, Object>> afterList = processingTimeFormat(fields, list);

        String resultPath = "";

        //导出的文件
        File exportFileAll = null;
        if ("word".equals(type)) {

            String finalPath = path;
            List<String> names = new ArrayList<>();
            AtomicInteger i = new AtomicInteger(1);
            List<File> files = afterList.stream().map(o -> {
                String fileName1 = "";
                String userName = MapUtil.getStr(o, "姓名");
                if (StringUtils.isNotBlank(userName)) {
                    if (names.contains(userName)) {
                        userName += i.getAndIncrement();
                    }
                    fileName1 = userName + "-" + fileName + DateUtil.now();
                    names.add(userName);
                }else {
                    fileName1 = fileName + DateUtil.now();
                }

                File file = WordUtil.exportWord(finalPath, exportUrl + "/" + IdUtil.simpleUUID(), fileName1, o);

                return file;
            }).collect(Collectors.toList());

            if (files.size() > 1) {
                File zipFile = new File(exportUrl + "/" + business.getName() + "_" + DateUtil.now() + ".zip");
                if (!zipFile.exists()) {
                    zipFile.createNewFile();
                    FileOutputStream fOutputStream = new FileOutputStream(zipFile);
                    ZipOutputStream zoutput = new ZipOutputStream(fOutputStream);
                    ZipUtil.zipFile(files, zoutput);
                    exportFileAll = zipFile;
                }
            } else {
                exportFileAll = files.get(0);
            }
        } else if ("excel".equals(type)) {

            exportFileAll = ExportUtil.returnData(path, afterList, fileName + DateUtil.now(), fields, exportUrl);

        }

        resultPath = exportFileAll.getPath().replace(exportUrl,"");

        PBFile exportFile = new PBFile();
        String exportFileId = IdUtil.simpleUUID();
        exportFile.setId(exportFileId);
        exportFile.setBaseInfo();
        exportFile.setName(exportFileAll.getName());
        exportFile.setPath(exportFileAll.getPath());

        pbFileRepository.save(exportFile);

        logService.save("业务数据", exportFileAll.getName(), OPERATION_EXPORT);

        return "/files" + resultPath;
    }

    @Override
    public String del(String id, List<String> documentIds) {

        if (CollUtil.isEmpty(documentIds)) {
            throw new BaseException(DATA_NOT_EXIST.getCode(), "请选择要删除的文档！");
        }

        Business business = businessService.get(id);
        String name = business.getName();
        String pname = business.getPname();
        IndexCoordinates indexCoordinates = QueryUtil.createIndex(name, pname);

        documentIds.stream().forEach(s ->{
            String delete = elasticsearchRestTemplate.delete(s, indexCoordinates);

            logService.save("业务文档", s, OPERATION_DEL);
        });

        return "success";
    }

    @Override
    public List<GroupVO> getGroupVOByRegion(String region) {

        List<Organization> allByRegion = organizationRepository.findAllByRegion(region);
        if (CollUtil.isEmpty(allByRegion)) {
            return null;
        }

        //只能获取当前机构下的文档
        List<String> list = organizationService.listChildrenIdsAndOneself(UserThreadLocal.getOrgId());
        if (CollUtil.isEmpty(list)) {
            return null;
        }

        List<GroupVO> collect = allByRegion.stream().filter(organization -> {
            String id = organization.getId();
            return list.contains(id);
        }).map(organization -> {

            GroupVO groupVO = new GroupVO();
            String orgName = organization.getOrgName();
            groupVO.setKey(orgName);
            int num = organization.getNumber() != null ? organization.getNumber() : 0;
            Long countBYOrgId = Long.valueOf(num);

            try {
                countBYOrgId = getCountBYOrgId(orgName);
            } catch (BaseException e) {
                log.warn("未找到军地协作，以单位内手动填写的数据为统计数量");
            }
            groupVO.setNum(countBYOrgId);
            return groupVO;
        }).collect(Collectors.toList());

        return collect;

    }

    @Override
    public List<GroupVO> getGroupByIndex(String indexName,Long startTime, Long endTime) {

        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
        BoolQueryBuilder qb = QueryBuilders.boolQuery();
        qb.filter(new QueryStringQueryBuilder("true").field("is_doc").defaultOperator(Operator.AND));
        qb.filter(QueryBuilders.rangeQuery("create_time").gte(startTime));
        qb.filter(QueryBuilders.rangeQuery("create_time").lt(endTime));
        queryBuilder.withQuery(qb);

        //按天分组统计
        DateHistogramAggregationBuilder dateHistogramAggregationBuilder = AggregationBuilders.dateHistogram("day")
                .field("create_time")
                .calendarInterval(DateHistogramInterval.DAY)
                .format("yyyy-MM-dd")
                .timeZone(ZoneId.of("Asia/Shanghai"))   //设置时区
                .minDocCount(0);

        queryBuilder.withQuery(qb);
        queryBuilder.addAggregation(dateHistogramAggregationBuilder);
        NativeSearchQuery build = queryBuilder.build();
        build.setMaxResults(0);

        String pinyin = PinyinUtil.getPinyin(indexName, "");
        IndexCoordinates indexCoordinates = IndexCoordinates.of(INDEX_PREFIX + pinyin);

        SearchHits<Object> search = elasticsearchRestTemplate.search(build, Object.class, indexCoordinates);
        Aggregations aggregations = search.getAggregations();
        if (aggregations == null) {
            return null;
        }
        ParsedDateHistogram day = (ParsedDateHistogram) aggregations.get("day");
        List<ParsedDateHistogram.ParsedBucket> buckets = (List<ParsedDateHistogram.ParsedBucket>) day.getBuckets();

        List<GroupVO> collect = buckets.stream().map(bucket -> {
            String keyAsString = bucket.getKeyAsString();

            long docCount = bucket.getDocCount();
            GroupVO groupVO = new GroupVO();
            groupVO.setKey(keyAsString);
            groupVO.setNum(docCount);

            return groupVO;
        }).collect(Collectors.toList());

        return collect;
    }

    @Override
    public List<GroupVO> getSpecifiedGroupByIndex(String businessId, Long startTime, Long endTime) {

        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
        BoolQueryBuilder qb = QueryBuilders.boolQuery();
        qb.filter(new QueryStringQueryBuilder("true").field("is_doc").defaultOperator(Operator.AND));

        qb.filter(new TermsQueryBuilder(ATTRIBUTION_ORG_NAMES +".keyword", UserThreadLocal.getOrg()));

        Business business = businessService.get(businessId);
        String occurredTime = business.getOccurredTime();
        //默认统计时间字段
        String timeFieldName = CREATE_TIME;
        if (StringUtils.isNotBlank(occurredTime)) {
            timeFieldName = occurredTime;
        }

        qb.filter(QueryBuilders.rangeQuery(timeFieldName).gte(startTime));
        qb.filter(QueryBuilders.rangeQuery(timeFieldName).lt(endTime));
        queryBuilder.withQuery(qb);

        //按天分组统计
        DateHistogramAggregationBuilder dateHistogramAggregationBuilder = AggregationBuilders.dateHistogram("day")
                .field(timeFieldName)
                .calendarInterval(DateHistogramInterval.DAY)
                .format("yyyy-MM-dd")
                .timeZone(ZoneId.of("Asia/Shanghai"))   //设置时区
                .minDocCount(0);

        queryBuilder.withQuery(qb);
        queryBuilder.addAggregation(dateHistogramAggregationBuilder);
        NativeSearchQuery build = queryBuilder.build();
        build.setMaxResults(0);

        IndexCoordinates index = businessService.getIndex(businessId);

        SearchHits<Object> search = elasticsearchRestTemplate.search(build, Object.class, index);
        Aggregations aggregations = search.getAggregations();
        if (aggregations == null) {
            return null;
        }
        ParsedDateHistogram day = (ParsedDateHistogram) aggregations.get("day");
        List<ParsedDateHistogram.ParsedBucket> buckets = (List<ParsedDateHistogram.ParsedBucket>) day.getBuckets();

        List<GroupVO> collect = buckets.stream().map(bucket -> {
            String keyAsString = bucket.getKeyAsString();
            long docCount = bucket.getDocCount();
            GroupVO groupVO = new GroupVO();
            groupVO.setKey(keyAsString);
            groupVO.setNum(docCount);

            return groupVO;
        }).collect(Collectors.toList());

        return collect;
    }

    @Override
    public List<GroupVO> getSpecifiedGroupByIndex(String businessId, Long startTime, Long endTime, String orgName, String timeType) {

        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
        BoolQueryBuilder qb = QueryBuilders.boolQuery();
        qb.filter(new QueryStringQueryBuilder("true").field("is_doc").defaultOperator(Operator.AND));
        qb.filter(new TermsQueryBuilder(ATTRIBUTION_ORG_NAMES +".keyword", orgName));

        Business business = businessService.get(businessId);
        String occurredTime = business.getOccurredTime();
        //默认统计时间字段
        String timeFieldName = CREATE_TIME;
        if (StringUtils.isNotBlank(occurredTime)) {
            timeFieldName = occurredTime;
        }

        qb.filter(QueryBuilders.rangeQuery(timeFieldName).gte(startTime));
        qb.filter(QueryBuilders.rangeQuery(timeFieldName).lt(endTime));
        queryBuilder.withQuery(qb);

        //时间维度
        DateHistogramAggregationBuilder dateHistogramAggregationBuilder = null;
        if ("day".equals(timeType)) {
            dateHistogramAggregationBuilder = AggregationBuilders.dateHistogram("day").field(timeFieldName)
                    .calendarInterval(DateHistogramInterval.DAY)
                    .format("yyyy-MM-dd");
        } else if ("month".equals(timeType)) {
            dateHistogramAggregationBuilder = AggregationBuilders.dateHistogram("day").field(timeFieldName)
                    .calendarInterval(DateHistogramInterval.MONTH)
                    .format("yyyy-MM");
        }else if ("year".equals(timeType)) {
            dateHistogramAggregationBuilder = AggregationBuilders.dateHistogram("day").field(timeFieldName)
                    .calendarInterval(DateHistogramInterval.YEAR)
                    .format("yyyy");
        } else {
            throw new BaseException(Status.DATA_NOT_EXIST.getCode(), "请选择统计纬度，按天或者按月！");
        }

        dateHistogramAggregationBuilder.timeZone(ZoneId.of("Asia/Shanghai"))   //设置时区
                .minDocCount(0);

        queryBuilder.withQuery(qb);
        queryBuilder.addAggregation(dateHistogramAggregationBuilder);
        NativeSearchQuery build = queryBuilder.build();
        build.setMaxResults(0);

        IndexCoordinates index = businessService.getIndex(businessId);

        SearchHits<Object> search = elasticsearchRestTemplate.search(build, Object.class, index);
        Aggregations aggregations = search.getAggregations();
        if (aggregations == null) {
            return null;
        }
        ParsedDateHistogram day = (ParsedDateHistogram) aggregations.get("day");
        List<ParsedDateHistogram.ParsedBucket> buckets = (List<ParsedDateHistogram.ParsedBucket>) day.getBuckets();

        List<GroupVO> collect = buckets.stream().map(bucket -> {
            String keyAsString = bucket.getKeyAsString();
            long docCount = bucket.getDocCount();
            GroupVO groupVO = new GroupVO();
            groupVO.setKey(keyAsString);
            groupVO.setNum(docCount);

            return groupVO;
        }).collect(Collectors.toList());

        return collect;
    }

    @Override
    public Long getCountBYOrgId(String orgName) {

        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
        BoolQueryBuilder qb = QueryBuilders.boolQuery();
        qb.filter(new TermsQueryBuilder(ATTRIBUTION_ORG_NAMES +".keyword", orgName));
        qb.filter(new QueryStringQueryBuilder("true").field("is_doc").defaultOperator(Operator.AND));
        queryBuilder.withQuery(qb);

        //查询军地协作的数量为单位的人数
        Business business = businessRepository.findByName(PERSON_DOCUMENT);
        if (business == null) {
            throw new BaseException(DATA_NOT_EXIST.getCode(), PERSON_DOCUMENT + "业务模块未找到请先添加此模块用于统计单位下的人数！");
        }

        IndexCoordinates index = businessService.getIndex(business.getId());

        long count = elasticsearchRestTemplate.count(queryBuilder.build(), index);

        return count;
    }

    @Override
    public Long getCountByOrgIds(String orgName, String businessId, Long startTime, Long endTime) {

        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
        BoolQueryBuilder qb = QueryBuilders.boolQuery();
        qb.filter(new TermsQueryBuilder(ATTRIBUTION_ORG_NAMES +".keyword", orgName));
        qb.filter(new TermsQueryBuilder("is_doc", true));

        Business business = businessService.get(businessId);
        String occurredTime = business.getOccurredTime();
        //默认统计时间字段
        String timeFieldName = CREATE_TIME;
        if (StringUtils.isNotBlank(occurredTime)) {
            timeFieldName = occurredTime;
        }

        qb.filter(QueryBuilders.rangeQuery(timeFieldName).gte(startTime));
        qb.filter(QueryBuilders.rangeQuery(timeFieldName).lt(endTime));

        queryBuilder.withQuery(qb);

        IndexCoordinates index = businessService.getIndex(businessId);
        long count = elasticsearchRestTemplate.count(queryBuilder.build(), index);
        return count;
    }

    @Override
    public List<GroupVO> listChildrenGroup(String businessId, String orgId, Long startTime, Long endTime) {

        //只要下级
        List<Organization> orgs = organizationRepository.findAllByPid(orgId);
        if (CollUtil.isEmpty(orgs)) {
            return null;
        }

        List<GroupVO> collect = orgs.stream().map(organization -> {
            String orgName = organization.getOrgName();

            Long countByOrgIds = getCountByOrgIds(orgName, businessId, startTime, endTime);

            GroupVO groupVO = new GroupVO();
            groupVO.setKey(orgName);
            groupVO.setNum(countByOrgIds);
            return groupVO;
        }).collect(Collectors.toList());
        return collect;
    }

    @Override
    public Long getCountBYOrgId(String orgId, Long startTime, Long endTime, String indexName) {

        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
        BoolQueryBuilder qb = QueryBuilders.boolQuery();
        qb.filter(QueryBuilders.rangeQuery("create_time").gte(startTime));
        qb.filter(QueryBuilders.rangeQuery("create_time").lt(endTime));
        Organization organization = organizationService.get(orgId);
        qb.filter(new TermsQueryBuilder(ATTRIBUTION_ORG_NAMES +".keyword", organization.getOrgName()));
        qb.filter(new QueryStringQueryBuilder("true").field("is_doc").defaultOperator(Operator.AND));
        queryBuilder.withQuery(qb);

        String pinyin = PinyinUtil.getPinyin(indexName, "");
        IndexCoordinates indexCoordinates = IndexCoordinates.of(INDEX_PREFIX + pinyin);
        long count = elasticsearchRestTemplate.count(queryBuilder.build(), indexCoordinates);

        return count;
    }

    @Override
    public void uploadAttachment(MultipartFile[] files, String businessId, String field) {


        if (StringUtils.isBlank(field)) {
            throw new BaseException(BAD_REQUEST.getCode(), "请选择附件所属字段！");
        }

        //获取所有字段用来验证文件名中需要确定唯一的字段
        Business business = businessService.get(businessId);
        List<BusinessField> fields = business.getFields();
        Map<String, String> mapping = new HashMap<>();
        List<String> collect = fields.stream().map(f -> {
            String key = f.getKey();
            String type = f.getType();
            mapping.put(key, type);
            return key;
        }).collect(Collectors.toList());

        if (!collect.contains(field)) {
            throw new BaseException(BAD_REQUEST.getCode(), "选择的附件字段未在业务中找到！");
        }

        //字段类型验证
        String type = mapping.get(field);
        if (!FILED_TYPE_FILE.equals(type)) {
            throw new BaseException(BAD_REQUEST.getCode(), "选择的附件字段必须是文件类型！");
        }

        IndexCoordinates index = businessService.getIndex(businessId);

        //校验文件名字身份证号是否都匹配，未匹配的都返回错误信息提示
        for (MultipartFile file : files) {

            String originalFilename = file.getOriginalFilename();

            UploadAttachmentDetaileVO uploadAttachmentDetaileVO = new UploadAttachmentDetaileVO();
            uploadAttachmentDetaileVO.setFileName(originalFilename);

            ParamVO param  = CommonUtil.getParam(originalFilename);


            String key = param.getKey();    //查询唯一标识的字段名
            String value = param.getValue(); //查询唯一标识的值

            if (!collect.contains(key)) {
                throw new BaseException(BAD_REQUEST.getCode(),"文件名中的 " + key + " 字段未在业务中找到！");

            }

            if (StringUtils.isBlank(value)) {
                throw new BaseException(BAD_REQUEST.getCode(),"文件名中未找唯一标识");

            }

            //根据身份证获取文档数据
            List<Object> objects = findAllParam(key,value, index);
            if (CollUtil.isEmpty(objects)) {
                throw new BaseException(BAD_REQUEST.getCode(),"文件名中的" + key + ":" + value + " 未在现有数据中找到！");
            }

            //填充附件信息
            try {
                String fileId = fileService.uploadFile(file);
                objects.stream().forEach(o -> {
                    Map<String, Object> map = (Map<String, Object>) o;
                    map.put(field, fileId); //目前只允许同一个附件字段只允许上传一个附件，新增多的直接覆盖

                    String id = MapUtil.getStr(map, "id");
                    updateById(id, map, index);

                });
            } catch (IOException e) {
                e.printStackTrace();
                throw new BaseException(BAD_REQUEST.getCode(),"文件上传失败");

            }
        }



    }

    @Override
    public List<Object> findAllParam(String key, String vaule, IndexCoordinates index) {


        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
        BoolQueryBuilder qb = QueryBuilders.boolQuery();
        qb.filter(new QueryStringQueryBuilder(vaule).field(key).defaultOperator(Operator.AND));

        queryBuilder.withQuery(qb);

        SearchHits<Object> search = elasticsearchRestTemplate.search(queryBuilder.build(), Object.class, index);
        List<Object> collect = search.stream().map(SearchHit::getContent).collect(Collectors.toList());

        return collect;
    }

    @Override
    public Object updateById(String id, Map<String, Object> param, IndexCoordinates index) {

        IndexQueryBuilder builder = new IndexQueryBuilder() //
                .withId(id) //
                .withObject(param);


        String index1 = elasticsearchRestTemplate.index(builder.build(), index);

        return index1;
    }


    /**
     * 解析Excel文档
     *
     * @param docFields
     * @param file
     * @param indexCoordinates
     * @return
     */
    public Object parsingExcel(List<DocField> docFields, File file, IndexCoordinates indexCoordinates, String fileId, UploadDocumentDTO uploadDocumentDTO) throws IOException {

        //起始行
        Integer index = ExportUtil.getIndex(docFields);

        List<Map<String, Object>> parsing = ExcelUtil.parsing(file, index);

        //失败数据，以及原因
        List<String> failure = new ArrayList<>();

        //键类型映射
        Map<String, String> mapping = new HashMap<>();

        //所有key
        List<String> keys = docFields.stream().map(docField -> {
            String key = docField.getKey();
            String type = docField.getType();
            mapping.put(key, type);
            return key;
        }).collect(Collectors.toList());

        //当前数据行
        AtomicInteger nowIndex = new AtomicInteger(index + 1);

        //如果指定了唯一字段，上传的数据必须要有这个字段
        String uniqueFieldName = uploadDocumentDTO.getUniqueFieldName();
        //必须要有单位
        String orgFieldName = uploadDocumentDTO.getOrgFieldName();

        //只存储已有的key
        List<IndexQuery> collect = parsing.stream().map(map -> {

            Map<String, Object> result = new HashMap<>();
            int andIncrement = nowIndex.getAndIncrement();

            //是否存在唯一值
            Boolean haveUnique = false;
            //没有设置字段就不需要
            if(StringUtils.isEmpty(uniqueFieldName)){
                haveUnique = true;
            }

            //是否有单位
            Boolean haveOrg = false;

            IndexQuery build = null;
            try {
                Set<Map.Entry<String, Object>> entries = map.entrySet();
                for (Map.Entry<String, Object> entry : entries) {
                    String key = entry.getKey();
                    String value = entry.getValue() + "";
                    if (keys.contains(key)) {

                        if (StringUtils.isNotBlank(uniqueFieldName) && key.equals(uniqueFieldName)) {
                            haveUnique = true;
                        }
                        if (key.equals(orgFieldName)) {
                            haveOrg = true;
                        }

                        String type = mapping.get(key);

                        //时间类型需要做处理
                        if ("date,time,month".contains(type)) {

                            if ( StringUtils.isNotBlank(value) && !value.equals("null")) {
                                Long dateLong = formatDate(key, value);

                                result.put(key, dateLong);
                            }else {
                                result.put(key, 0);
                            }

                        } else {
                            result.put(key, entry.getValue());
                        }

                        specifiedField(key, value, uploadDocumentDTO, result, indexCoordinates);
                    }
                }

                if (!haveUnique) {
                    throw new BaseException(DATA_NOT_EXIST.getCode(), "未找到唯一字段 " + uniqueFieldName + "的值");
                }

                if (!haveOrg) {
                    throw new BaseException(DATA_NOT_EXIST.getCode(), "未找到单位字段 " + orgFieldName + "的值");
                }

                IndexQueryBuilder indexQueryBuilder = indexDoc(result, fileId, indexCoordinates);
                build = indexQueryBuilder.build();
            } catch (BaseException e) {
                String message = e.getMessage();
                failure.add("第" + andIncrement + "行数据异常：" + message);
                return null;
            }
            return build;
        }).collect(Collectors.toList());

        collect = collect.stream().filter(indexQuery -> indexQuery != null).collect(Collectors.toList());

        //有上传失败的直接返回失败
        if (CollUtil.isNotEmpty(failure)) {
            String join = CollUtil.join(failure, ";");
            throw new BaseException(DATA_EXIST.getCode(), "数据上传失败，请确认后重试 :" + join);
        }

        if (CollUtil.isEmpty(collect)) {
            return null;
        }


        List<String> list = elasticsearchRestTemplate.bulkIndex(collect, indexCoordinates);

        return list;
    }


    /**
     * 格式化时间
     *
     * @param date
     * @return
     */
    public Long formatDate(String key, String date) {

        long time = 0;
        try {
            time = com.zkjl.protect_business.utils.DateUtil.parseDate(date);

        } catch (Exception e) {
            e.printStackTrace();
            throw new BaseException(BAD_REQUEST.getCode(), key + ":" + date + " ，时间格式不正确，请使用xxxx年xx月xx日 或者 xxxx-xx-xx");
        }
        return time;
    }


    /**
     * 索引文档
     *
     * @param param
     * @param fileId
     * @return
     */
    public IndexQueryBuilder indexDoc(Map<String, Object> param, String fileId,IndexCoordinates indexCoordinates) {

        //数据生成id确保数据唯一性
        String jsonStr = JSONUtil.toJsonStr(param);
        Digester md5 = new Digester(DigestAlgorithm.MD5);
        String id = md5.digestHex(jsonStr);
        String id1 = MapUtil.getStr(param, "id");
        if (StringUtils.isNotBlank(id1)) {
            param.put("id", id1);
            id = id1;
        }else {
            //重复数据直接覆盖
            param.put("id", id);
        }
        param.put("file_id", fileId);
        param.put("is_doc", "true"); //所有上传的数据文档单独标识，以便后面做数据统计
        param.put("create_user_id", UserThreadLocal.getUserId());
        param.put("create_user_name", UserThreadLocal.getUserName());
        param.put("create_org_id", UserThreadLocal.getOrgId());
        param.put("create_org_name", UserThreadLocal.getOrg());
        param.put("create_time", System.currentTimeMillis());

        IndexQueryBuilder builder = new IndexQueryBuilder() //
                .withId(id) //
                .withObject(param);

        return builder;

    }




    /**
     * 解析word文档
     *
     * @param docFields
     * @param file
     * @return
     * @throws IOException
     */
    public Object parsingWord(List<DocField> docFields, File file, IndexCoordinates indexCoordinates,String fileId,UploadDocumentDTO uploadDocumentDTO) throws IOException {


        //解析所有数据
        Map<String, Object> map = wordUtil.parsing(file, uploadPath);

        Map<String, Object> result = new HashMap<>();

        //如果指定了唯一字段，上传的数据必须要有这个字段
        String uniqueFieldName = uploadDocumentDTO.getUniqueFieldName();
        //必须要有单位
        String orgFieldName = uploadDocumentDTO.getOrgFieldName();

        //是否存在唯一值
        Boolean haveUnique = false;
        //没有设置字段就不需要
        if(StringUtils.isEmpty(uniqueFieldName)){
            haveUnique = true;
        }

        //是否有单位
        Boolean haveOrg = false;

        for (DocField docField : docFields) {

            String key = docField.getKey();
            String location = docField.getLocation();
            String type = docField.getType();
            Object value = map.get(location);

            if (StringUtils.isNotBlank(uniqueFieldName) && key.equals(uniqueFieldName)) {
                haveUnique = true;
            }
            if (key.equals(orgFieldName)) {
                haveOrg = true;
            }

            if ("date,time,month".contains(type) ) {
                if (StringUtils.isNotBlank(value + "")) {
                    Long date = formatDate(key, value + "");
                    result.put(key, date);
                }else {
                    result.put(key, 0);
                }

            } else {
                result.put(key, value);
            }

            specifiedField(key, value, uploadDocumentDTO, result, indexCoordinates);
        }

        if (!haveUnique) {
            throw new BaseException(DATA_NOT_EXIST.getCode(), "未找到唯一字段 " + uniqueFieldName + "的值");
        }

        if (!haveOrg) {
            throw new BaseException(DATA_NOT_EXIST.getCode(), "未找到单位字段 " + orgFieldName + "的值");
        }

        IndexQueryBuilder indexQueryBuilder = indexDoc(result, fileId, indexCoordinates);
        String index = elasticsearchRestTemplate.index(indexQueryBuilder.build(), indexCoordinates);
        return index;

    }


    /**
     * 处理指定字段
     * @param key  字段名
     * @param value 字段值
     * @param uploadDocumentDTO
     * @param result
     * @param indexCoordinates
     */
    public void specifiedField(String key, Object value, UploadDocumentDTO uploadDocumentDTO, Map<String, Object> result, IndexCoordinates indexCoordinates) {

        //指定身份证和单位的字段
        String idCardFieldName = uploadDocumentDTO.getIdCardFieldName();
        String orgFieldName = uploadDocumentDTO.getOrgFieldName();
        String uniqueFieldName = uploadDocumentDTO.getUniqueFieldName();
        String occurredTime = uploadDocumentDTO.getOccurredTime();

        //字段和业务设置的匹配
        if (key.equals(orgFieldName)) {
            //校验值是否在系统中存在
            Organization organization = organizationService.find(value + "");
            if (organization != null) {
                result.put(ATTRIBUTION_ORG_ID, organization.getId());
                result.put(ATTRIBUTION_ORG_NAME, organization.getOrgName());
            }

            List<String> allPame = organizationService.findAllPame(value + "");
            if (CollUtil.isEmpty(allPame)) {
                throw new BaseException(DATA_NOT_EXIST.getCode(), "\"" + value + "\" 未在系统已录入单位中找到，请确认后重试！");
            }
            result.put(ATTRIBUTION_ORG_NAMES, allPame);

        }
        //身份证号字段
        if (key.equals(idCardFieldName)) {
            result.put(ID_CARD, value);
        }
        //发生时间匹配
        if (key.equals(occurredTime)) {
            Long dateLong = formatDate(key, value + "");
            result.put(OCCURRED_TIME, dateLong);
        }
        //唯一字段 增量覆盖
        if (key.equals(uniqueFieldName)) {
            if (StringUtils.isBlank(value + "")) {
                throw new BaseException(BAD_REQUEST.getCode(), "唯一标识字段 \"" + uniqueFieldName + "\"的值不能为空！");
            }

            Object o = get(indexCoordinates, key, value);
            if (o != null) {
                Map<String, Object> map1 = (Map<String, Object>) o;
                String id = MapUtil.getStr(map1, "id");
                map1.putAll(result);

                result.putAll(map1);
                result.put("id", id);

            }
        }

    }




}
